// ======================== 📦 类型定义层 ========================

/**
 * 🌟 路径类型：支持点分隔符或数组形式
 * @example
 * "user.address.street" => ['user', 'address', 'street']
 * ['order', 'items.0.name'] => ['order', 'items', '0', 'name']
 */
export type Path = string | string[];

/**
 * 🔄 值处理器：用于转换源值的函数
 * @param value - 当前处理的值
 * @param context - 映射上下文对象
 * @returns 处理后的新值
 * @example
 * (val) => val.toUpperCase() // 转为大写
 */
export type ValueProcessor<T = any> = (value: T, context: MappingContext) => T;

/**
 * 🔍 条件断言：返回布尔值决定是否执行映射
 * @example
 * (ctx) => ctx.value !== null // 仅当值不为null时映射
 */
export type ConditionPredicate = (context: MappingContext) => boolean;

/**
 * 📜 映射规则定义
 * @example - 基本用法
 * { target: 'userName', source: 'name' }
 * @example - 带转换器
 * {
 *   target: 'price',
 *   transform: [Transformers.number.round(2), Transformers.number.currency('¥')]
 * }
 */
export interface MappingRule<T = any> {
  /** 🎯 目标属性路径（支持嵌套路径）*/
  target: Path;
  /** 📍 来源属性路径（默认与target相同）*/
  source?: Path;
  /** 🛠️ 值转换管道（按数组顺序执行）*/
  transform?: ValueProcessor<T> | ValueProcessor<T>[];
  /** ⚖️ 映射条件（返回true时执行）*/
  when?: ConditionPredicate;
  /** 🛡️ 默认值（当源值为undefined/null时使用）*/
  default?: T;
  /** ⚙️ 本地配置（覆盖全局配置）*/
  config?: Partial<MappingConfig>;
}

/**
 * ⚙️ 映射全局配置
 * @example
 * { strict: true, nullPolicy: 'set-default' }
 */
export interface MappingConfig {
  /** 🚨 严格模式：路径不存在时抛出错误 */
  strict: boolean;
  /** 🕳️ 空值策略：
   * - 'ignore'：跳过设置
   * - 'set-null'：设为null
   * - 'set-default'：使用默认值 */
  nullPolicy: 'ignore' | 'set-null' | 'set-default';
  /** 🤖 自动类型转换（如字符串转Date）*/
  autoType: boolean;
  /** 🗄️ 启用路径缓存（提升性能）*/
  cachePaths: boolean;
}

/**
 * 📌 映射上下文对象（贯穿整个处理流程）
 * @example 在转换器中访问上下文：
 * (val, ctx) => `${val}_${ctx.source.id}`
 */
export interface MappingContext {
  /** 🗃️ 源数据对象 */
  source: Record<string, any>;
  /** 📦 目标数据对象 */
  target: Record<string, any>;
  /** 📜 当前处理规则 */
  rule: NormalizedRule;
  /** ⚙️ 当前生效配置 */
  config: Readonly<MappingConfig>;
  /** 🎛️ 当前处理的值 */
  value: any;
  /** 🗺️ 当前源路径（解析后数组）*/
  sourcePath: string[];
  /** 🎯 当前目标路径（解析后数组）*/
  targetPath: string[];
}

/**
 * 📄 标准化后的映射规则（内部使用）
 */
export type NormalizedRule = Omit<MappingRule, 'target' | 'source'> & {
  targetPath: string[];
  sourcePath: string[];
  config: Partial<MappingConfig>;
};

// ======================== 🔌 插件系统 ========================

/**
 * 🔌 插件钩子类型定义
 * @example - 典型插件结构：
 * {
 *   beforeMap: (ctx) => console.time('mapping'),
 *   afterMap: (ctx) => console.timeEnd('mapping')
 * }
 */
export interface PluginHooks {
  /** 🏁 映射开始前触发 */
  beforeMap: (context: { source: any; target: any; rules: any[] }) => void | boolean;
  /** 🏁 映射结束后触发 */
  afterMap: (context: { source: any; target: any; rules: any[] }) => void;
  /** ⏳ 单条规则执行前触发 */
  beforeRule: (context: MappingContext) => void | boolean;
  /** ✅ 单条规则执行后触发 */
  afterRule: (context: MappingContext) => void;
  /** 🚨 错误发生时触发 */
  onError: (error: Error, context: MappingContext) => void | boolean;
}

export type MapperPlugin = Partial<PluginHooks>;
